package com.mylims.ifdc.common.plugin;

import com.mylims.ifdc.common.config.SpringContextHolder;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.springframework.messaging.simp.SimpMessagingTemplate;

import java.io.Serializable;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

@Plugin(name = "WebSocketAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
public class WebSocketAppender extends AbstractAppender {
    private SimpMessagingTemplate messagingTemplate;

    private final BlockingQueue<String> logQueue = new LinkedBlockingQueue<>(1000);

    public WebSocketAppender(String name, Filter filter, Layout<? extends Serializable> layout) {
        super(name, filter, layout, true, Property.EMPTY_ARRAY);
        startBackgroundThread();
    }

    @Override
    public void append(LogEvent event) {
        try {
            String s = getLayout().toSerializable(event).toString();
            logQueue.put(s);
        } catch (Exception e) {
            //e.printStackTrace();
        }
    }

    private void startBackgroundThread() {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    String log = logQueue.take();
                    this.getMessagingTemplatenow().convertAndSend("/topic/logs", log);
                } catch (Exception e) {
                    //e.printStackTrace();
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
    }

    @PluginFactory
    public static WebSocketAppender createAppender(
            @PluginAttribute("name") String name,
            @PluginElement("Layout") Layout<? extends Serializable> layout,
            @PluginElement("Filter") Filter filter) {
        return new WebSocketAppender(name, filter, layout);
    }


    public SimpMessagingTemplate getMessagingTemplatenow() {
        if (this.messagingTemplate == null) {
            try {
                this.messagingTemplate = SpringContextHolder.getBean("brokerMessagingTemplate", SimpMessagingTemplate.class);
            } catch (Exception e) {
                //e.printStackTrace();
            }
        }
        return this.messagingTemplate;
    }
}
